package com.sqlSession;

import com.pojo.Configuration;
import com.pojo.MappedStatement;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.util.List;

/**
 * Created with IDEA by ChouFy on 2020/2/20.
 *
 * @author Zhoufy
 */
public class DefaultSqlSession implements SqlSession {


    private Configuration configuration;

    private Class thisClazz = this.getClass();


    public DefaultSqlSession(Configuration configuration) {
        this.configuration = configuration;
    }


    @Override
    public <E> List<E> select(String statementId, Object... arguments) throws Exception {
        SimpleExecutor executor = new SimpleExecutor();
        MappedStatement mappedStatement = configuration.getMap().get(statementId);
        List<E> query = executor.query(configuration, mappedStatement, arguments);
        return query;
    }


    public int update(String statementId, Object... arguments) throws Exception {
        SimpleExecutor executor = new SimpleExecutor();
        MappedStatement mappedStatement = configuration.getMap().get(statementId);
        return executor.update(configuration, mappedStatement, arguments);
    }

    public int insert(String statementId, Object... arguments) throws Exception {
        SimpleExecutor executor = new SimpleExecutor();
        MappedStatement mappedStatement = configuration.getMap().get(statementId);
        return executor.update(configuration, mappedStatement, arguments);
    }


    public int delete(String statementId, Object... arguments) throws Exception {
        SimpleExecutor executor = new SimpleExecutor();
        MappedStatement mappedStatement = configuration.getMap().get(statementId);
        return executor.update(configuration, mappedStatement, arguments);
    }


    @Override
    public <T> T getMapper(Class<?> clazz) throws Exception {
        //  使用JDK动态代理来为dao动态生成代理对象 并返回

        Object proxyInstance = Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{clazz}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                String methodName = method.getName();


                Type genericReturnType = method.getGenericReturnType();

                String className = method.getDeclaringClass().getName();

                String statementId = className + "." + methodName;
                System.out.println("statementId:" + statementId);
                MappedStatement mappedStatement = configuration.getMap().get(statementId);
                String labelName = mappedStatement.getLabelName();

                if ("select".equals(labelName)) {
                    List list = select(statementId, args);
                    if(genericReturnType instanceof ParameterizedType){
                        return list;
                    }
                    if(list.size() > 0){
                        return list.get(0);
                    }
                    return null;
                } else {
                    return update(statementId, args);
                }

//               Constructor constructor = thisClazz.getDeclaredConstructor(new Class[]{Configuration.class});
//               Object objects = constructor.newInstance(configuration);
//               Method invokeMethod = thisClazz.getMethod(labelName, new Class[]{String.class, Object[].class});
//               return invokeMethod.invoke(objects, statementId, args);

            }
        });
        return (T) proxyInstance;
    }
}
